/**
 * 
 */
package com.lanswon.qzsmk.service.cardManageService.impl;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.lanswon.qzsmk.base.AccountContants;
import com.lanswon.qzsmk.base.AppContants;
import com.lanswon.qzsmk.base.CardContants;
import com.lanswon.qzsmk.base.DwzPage;
import com.lanswon.qzsmk.dao.AppKindMapper;
import com.lanswon.qzsmk.dao.AppOpenRegMapper;
import com.lanswon.qzsmk.dao.BusiParamMapper;
import com.lanswon.qzsmk.dao.BusinessMapper;
import com.lanswon.qzsmk.dao.CardControlMapper;
import com.lanswon.qzsmk.dao.CardDataMapper;
import com.lanswon.qzsmk.dao.CardManageMapper;
import com.lanswon.qzsmk.dao.CardProdunctDefinitionMapper;
import com.lanswon.qzsmk.dao.CardTypeMapper;
import com.lanswon.qzsmk.dao.CertMapper;
import com.lanswon.qzsmk.dao.CertificateMapper;
import com.lanswon.qzsmk.dao.FeeRulesMapper;
import com.lanswon.qzsmk.dao.PersonalMapper;
import com.lanswon.qzsmk.dao.RefundViewMapper;
import com.lanswon.qzsmk.dao.SubaccountPersonalMapper;
import com.lanswon.qzsmk.dao.TransGlideMapper;
import com.lanswon.qzsmk.dao.TxnDtlMapper;
import com.lanswon.qzsmk.exception.ApplicationException;
import com.lanswon.qzsmk.exception.ErrorCode;
import com.lanswon.qzsmk.model.ActiveUser;
import com.lanswon.qzsmk.model.AppKind;
import com.lanswon.qzsmk.model.AppOpenReg;
import com.lanswon.qzsmk.model.Business;
import com.lanswon.qzsmk.model.CardControl;
import com.lanswon.qzsmk.model.CardData;
import com.lanswon.qzsmk.model.CardManage;
import com.lanswon.qzsmk.model.Cert;
import com.lanswon.qzsmk.model.FeeRules;
import com.lanswon.qzsmk.model.Personal;
import com.lanswon.qzsmk.model.RefundView;
import com.lanswon.qzsmk.model.SubaccountPersonal;
import com.lanswon.qzsmk.model.TransGlide;
import com.lanswon.qzsmk.model.TxnDtl;
import com.lanswon.qzsmk.service.cardManageService.RefundService;
import com.lanswon.qzsmk.service.preService.BikeService;
import com.lanswon.qzsmk.util.SequenceNumberUtil;
import com.lanswon.qzsmk.vo.QueryRefundInfoCondition;
import com.lanswon.qzsmk.vo.RefundDetailInfo;
import com.lanswon.qzsmk.vo.RefundInfo;
import com.lanswon.qzsmk.vo.ResponseHead;
import com.lanswon.qzsmk.vo.VoucherVo;

/**
 * @author sun
 *
 */
@Service
public class RefundServiceImpl implements RefundService {

	@Autowired
	RefundViewMapper rm;
	
	@Autowired
	CardTypeMapper ctm;
	
	@Autowired
	CertificateMapper cm;
	
	@Autowired
	SubaccountPersonalMapper spm;
	
	@Autowired
	BusiParamMapper bpm;
	
	@Autowired
	CardControlMapper cacm;

	@Autowired
	CardDataMapper cdm;
	
	@Autowired
	CardManageMapper cmm;
	
	@Autowired
	TxnDtlMapper tdm;
	
	@Autowired
	AppOpenRegMapper aorm;
	
	@Autowired
	CertMapper cem;
	
	@Autowired
	BusinessMapper bm;
	
	@Autowired
	CardProdunctDefinitionMapper cpdm;
	
	@Autowired
	FeeRulesMapper frm;
	
	@Autowired
	AppKindMapper akm;
	
	@Autowired
	TransGlideMapper tgm;
	
	@Autowired
	PersonalMapper pm;
	
	@Autowired 
	BikeService bikeService;
	
	private static String allowStatus_no = "01";
	
	private static String code0001 = "0001";
	
	private static String code0000 = "0000";
	@Override
	public DwzPage<RefundInfo> queryRefundList(QueryRefundInfoCondition ri) {
		if(StringUtils.isEmpty(ri.getCardpCode())){
			ri.setCardpCode1(CardContants.CARD_P_CODE_WF);
			ri.setCardpCode2(CardContants.CARD_P_CODE_JS);
		}
		
		ri.setCardStatus1(CardContants.CARD_STATE_CANCELLATION_NO_CARD);
		ri.setCardStatus2(CardContants.CARD_STATE_CANCELLATION_HAS_CARD);
		
		List<RefundView> list = rm.queryRefund(ri);
		List<RefundInfo> l = new ArrayList<>();
		for(RefundView rv:list){
			RefundInfo r = new RefundInfo();
			r.setCardStatusName(CardContants.getCardStatusNameByCode(rv.getCardStatus()));
//			r.setCardTypeName(ctm.queryCardTypeByCode(rv.getCardTypecode()).getCardTypeName());
			r.setCardTypeName(rv.getCardTypeName());
			r.setCertNo(rv.getCertNo());
			r.setCitizenCardNo(rv.getCitizenCardNo());
			r.setPaperNo(rv.getPaperNo());
//			r.setPaperTypeName(cm.queryCertificateByCode(rv.getPaperType()).getCertificatesName());
			r.setPaperTypeName(rv.getPaperTypeName());
			r.setCustomerName(rv.getCustomerName());
//			r.setCardpCodeName(cpdm.queryCardPCode(rv.getCardpCode()).getCardpName());
			r.setCardpCodeName(rv.getCardpName());
			r.setLogoutDate(rv.getLogoutDate());
			l.add(r);
		}

		DwzPage<RefundInfo> dp = new DwzPage<RefundInfo>(ri.getCurrentPage(), ri.getNumPerPage(), l.size());

		dp.setList(l);
		dp.setList(dp.getPagedList());

		return dp;
	}

	@Override
	public List<RefundDetailInfo> queryDetailInfoByCitizenCardNo(String citizenCardNo) throws Exception {
		if(StringUtils.isEmpty(citizenCardNo)){
			throw new ApplicationException(ErrorCode.OBJECT_IS_NULL, "CitizenCardNo is null!!!");
		}
		List<RefundDetailInfo> list=rm.queryAboutDetail(citizenCardNo);
		for(RefundDetailInfo refundDetailInfo:list){
			if(refundDetailInfo.getAppFlag().equals(AppContants.APP_FLAG_BIKE)){
				JSONObject jsonObject=bikeService.queryBikeUserByCitizenCardNo(citizenCardNo);
				ResponseHead g =JSON.parseObject(jsonObject.getString("head"), ResponseHead.class);
				if(code0001.equals(g.getRsltcode())){
		        	throw new ApplicationException(ErrorCode.OTHER_EXCEPTION, "当前卡片未开通自行车应用");
		        }
				jsonObject=jsonObject.getJSONObject("body");
				if(!jsonObject.getString("deposit").equals(refundDetailInfo.getDeposit())){
					throw new ApplicationException(ErrorCode.OTHER_EXCEPTION, "系统自行车押金和自行系统押金不一致");
				}
				String vipno=jsonObject.getString("vipno");
				String vipcardsn=jsonObject.getString("vipcardsn");
				jsonObject=bikeService.memberBorrowOrBackLastTime( vipno, vipcardsn);
				jsonObject = jsonObject.getJSONObject("body");
		        String allowStatus = jsonObject.getString("allow");//借还状态
		        if(allowStatus_no.equals(allowStatus)){
		        	throw new ApplicationException(ErrorCode.OTHER_EXCEPTION, "当前卡片会员状态：挂失或者注销，禁止借车");
		        }
				String balance=jsonObject.getString("balance");
				refundDetailInfo.setBalance(balance);
				SecurityUtils.getSubject().getSession().setAttribute("vipno", vipno);
			}
		}
		return list;
	}

	@Override
	@Transactional(rollbackFor=Exception.class)
	public VoucherVo commitRefundInfo(String citizenCardNo,String balance) throws ApplicationException {
		Date now = new Date();
		ActiveUser activeUser  = (ActiveUser) SecurityUtils.getSubject().getSession().getAttribute("activeUser");
		if(activeUser == null){
			activeUser = new ActiveUser();
			activeUser.setUserName("用户");
			activeUser.setLoginName("用户");
			activeUser.setBranchName("互联网端");
			activeUser.setBranchNo("99999999");
			activeUser.setUserNo(99999999);
			activeUser.setUserId(99999999);
		}
		
		CardData cd = cdm.queryCardDataByCitizenCardNo(citizenCardNo);
		Personal p = pm.queryPersonalByCustomerNo(cd.getCustomerNo());
		CardControl cc = cacm.queryCardControlByCardDataId(cd.getCardDataId());
		

		Cert ce = new Cert();
		ce.setCertNo(SequenceNumberUtil.generatorCertNo());
		ce.setCertType(CardContants.REFUND_REGISTRATION_DEPOSIT);
		ce.setCardpCode(cd.getCardpCode());
		ce.setCardTypecode(cd.getCardTypecode());
		ce.setName(p.getCustomerName());
		ce.setPaperNo(p.getPaperNo());
		ce.setPaperType(p.getPaperType());
		ce.setBranch(activeUser.getBranchName());
		ce.setBranchNo(activeUser.getBranchNo());
//		ce.setAgentName(p.getAgentName());
//		ce.setAgentPaperNo(refundInfo.getAgentPaperNo());
//		ce.setAgentPapertype(refundInfo.getAgentPapertype());
		ce.setCardControlId(cc.getCardControlId());
		ce.setCrtDate(new Date());
		ce.setCrtOperator(activeUser.getUserNo().toString());
		ce.setLastOperator(activeUser.getUserNo().toString());
		ce.setLastDate(new Date());
		
		Business b = new Business();
		b.setBusinessNo(SequenceNumberUtil.generatorBusinessNo());
		b.setCustomerNo(cd.getCustomerNo());
		b.setTransCode("交易代码");
//		b.setAgentName(null);
//		b.setAgentPaperNo(refundInfo.getAgentPaperNo());
//		b.setAgentPapertype(refundInfo.getAgentPapertype());
//		b.setAgentPhone(refundInfo.getAgentPhone());
		b.setBusiNum(1);
		b.setTellerNo(activeUser.getUserNo().toString());
		b.setTransDate(now);// 交易日期
		b.setSeqStatus(CardContants.LSZT_NORMAL);
		b.setRemark("联名卡注销退押金业务");
		b.setCardControlId(cc.getCardControlId());
		b.setCertNo(ce.getCertNo());
		bm.insert(b);
		
		ce.setBusinessNo(b.getBusinessNo());
		cem.insert(ce);
		
		
		CardManage cme = new CardManage();
		cme.setProcessId(UUID.randomUUID().toString().replace("-", ""));
		cme.setApplyBranch(activeUser.getBranchName());
		cme.setApplyBranchNo(activeUser.getBranchNo());
		cme.setApplyDate(new Date());
		cme.setApplyTellerNo(activeUser.getUserNo().toString());
//		cme.setProcessCode(CardContants.CARD_PROC_CARD_PEND);
		cme.setProcessName("退款");
		cme.setCitizenCardNo(citizenCardNo);
		cme.setApplyWay(CardContants.CLAIM_METHOD_COMPANY);// 1.零星2.单位规模3.社区规模4.网上规模9.其他规模
		cme.setBusinessNo(b.getBusinessNo());
		cme.setCertNo(ce.getCertNo());
		cmm.insert(cme);
		
		cc.setCurrProcId(cme.getProcessId());
		
		cacm.updateCardControl(cc);
		
		SubaccountPersonal sp = spm.querySubaccountPersonalByWallet(citizenCardNo, AccountContants.WALLET_TYPE_ELECTRONIC_WALLET);
		
	
		
		int refundFeeBln=0;//退款押金
		int logofMoney=0;//退款应用金额
		//该卡所有未退款的应用
		List<AppOpenReg> la = aorm.queryAppOpenByCitizenCardNoAndIsdeposit(citizenCardNo,AccountContants.IS_DEPOSIT_NO);
		
		List<AppKind> appKinds=new ArrayList<>();//区别自行车应用和其他应用
		for(AppOpenReg aor:la){
			aor.setIsDeposit(AccountContants.IS_DEPOSIT_YES);
			aor.setLastDate(new Date());
			aor.setLastOperator(activeUser.getUserNo().toString());
			aorm.update(aor);
			
			AppKind ak = akm.queryAppKindByTypeCode(Integer.valueOf(aor.getAppType()));
			appKinds.add(ak);
			
			FeeRules fr = frm.queryFeeByAppTypeAndCardPCode(aor.getAppType(),cd.getCardpCode(),AccountContants.FEE_TYPE_DEPOSIT);
			if(fr != null && fr.getFeeBln().compareTo(new BigDecimal(0)) != 0){	
				refundFeeBln+=fr.getFeeBln().intValue();
				if(ak.getAppFlag().equals(AppContants.APP_FLAG_BIKE)){
					if(balance!=""&&balance!=null){
						logofMoney+=new BigDecimal(balance).intValue();
					}
				}
				
				// 当日交易明细
				TxnDtl td = new TxnDtl();
//					td. setCrdNo("") ;
//					td. setCardSeqNo(""); 
//					td. setCrdUniqueNo("");
				td. setCitizenCardNo(citizenCardNo);
//					td. setSubaccountNo(String subaccountNo);
				td. setIssCityCd(CardContants.CITY_CODE);		
				td. setTxnCityCd(CardContants.CITY_CODE) ;
				td. setCrdIndustCd(String.valueOf(citizenCardNo.charAt(3)));//卡行业代码
				td. setAppFlag(ak.getAppFlag());
//					td. setCrdPhysTp(String crdPhysTp) ;//卡物理类型 		  
//					td.setCtSeq(String ctSeq);//中心流水号 			   
//					td. setCtDt(Date ctDt) ;//中心时间
				td. setCashFlag(AccountContants.CASH_FLAG_PAY); //现金收付标志 0.无,1.收取 2.支出,3.收支
//					td. setTxnTp(bv.getCrdTxnType());//	卡交易类型

				td. setTxnDt(DateFormatUtils.format(now, "yyyyMMddHHmmss"));			   
//					td. setTxnBalBef(totalBalance) ;//账户交易前余额		 
//					td. setTxnBalAft(cardWallet.getTotalBalance());			    
				if(ak.getAppFlag().equals(AppContants.APP_FLAG_BIKE)){
					td.setFeeTp(AccountContants.FEE_TYPE_DEPOSIT);//费用类型  0.本金 1:工本费 2.交易手续费 3:租金4:押金
					td.setTxnAmt(fr.getFeeBln().add(new BigDecimal(balance))) ;//交易金额
					td. setTxnBalBef(new BigDecimal(balance)) ;//账户交易前余额		 
					td. setTxnBalAft(new BigDecimal(0));
				}else{
					td. setFeeTp(AccountContants.FEE_TYPE_DEPOSIT);//费用类型  0.本金 1:工本费 2.交易手续费 3:租金4:押金
					td. setTxnAmt(fr.getFeeBln()) ;	
//					td. setCrdBalAft(sp.getTotalBalance());
//					td. setCrdBalBef(sp.getTotalBalance()) ;//卡交易前 余额
				}
				
//					td. setSetDt(Date setDt);//结算日期			   
					td. setFeeTp(AccountContants.FEE_TYPE_DEPOSIT);//费用类型  0.本金 1:工本费 2.交易手续费 3:租金4:押金			    
					td. setAcceptTp(AccountContants.ACCEPTANCE_TYPE_NET);//受理类型 表示终端的归属，由上传的终端代码决定：01-网点 06-商户
				    td. setAcceptCusNo(activeUser.getBranchNo()) ;//受理商户/网点编号			  
//				    td. setTermNo("");//终端代码			    
//					td. setTermSeq(String termSeq) ;//终端流水号			   
//				    td.setSamNo(bv.getSamNo());//			  
//					td. setSamSeq(String samSeq) ;			    
//					td. setTxnFileName("");//交易文件名称
//					td. setPkgRecOrd(Integer pkgRecOrd) ;//所属数据包记录序号 
//				    td. setDivFactor(bv.getDivFactor());
//				    td.setTxnTac(bv.getTxnTac());
//				    td. setTxnCharcFld(String txnCharcFld) ;//交易个性域
			    td. setTxnTstFlg(AccountContants.TRANSACTION_TEST_FLAG_COMMON) ;//交易测试标志 "0"-普通; "1"-测试			   
//				    td. setErrCode(String errCode);//错误代码 记录级错误			    
//				    td. setTxnAdjFlg(String txnAdjFlg);//交易流水标志 "00" 正常 "41" 撤销			   
//				    td.setAdjCtSeq(String adjCtSeq) ;//关联中心流水号			    
//				    td. setAdjCtDt(Date adjCtDt);//关联中心时间
//				    td.setTxnMac1(String txnMac1) ;
//				    td.setTxnMac2(String txnMac2);			  
//				    td.setAdjSetDt(Date adjSetDt) ;//关联结算日期			   
//				    td. setLastTxnCnt(cardWallet.getTotalReloadCnt()) ;//上一次交易卡计数器			   
//				    td. setLastTxnDt(Date lastTxnDt) ;//上一次交易时间			 
//				    td. setLastTxnAmt(BigDecimal lastTxnAmt) ;//上一次交易金额			   
//				    td. setCurrCount(Integer currCount);//当前计数器值 		   
			    td. setWarrantid(ce.getCertNo()) ;//凭证号
//				    td.setOutWarrantid(String outWarrantid);//外部凭证号			   
			    td. setOprNo(activeUser.getUserNo().toString());//操作员编号/终端操作员编号 			  
//				    td. setLocalTxnSeq(String localTxnSeq);//本地流水号			    
			    td. setTxnAttr(AccountContants.TXNTP_REFUND) ;//交易性质 			   
//				    td. setStationId(String stationId) ;//采集点编号
//				    td. setPosCarrId(String posCarrId);//POS机载体编号
			    td. setCrdCityCd(CardContants.CITY_CODE);//卡城市代码
			    td. setCardType(cd.getCardTypecode());
			    td. setRsvdFlags(AccountContants.TXNTP_REFUND);	//预留标志组		   
//				    td. setRsvdFld(String rsvdFld);//保留字段
//				    td.setFileGenDate(Date fileGenDate) ;//文件生成日期 
//				    td.setTxnType(AccountContants.TRADE_TYPE_BUS) ;//终端交易类型 
			    td.setTxnDate(DateFormatUtils.format(now, "yyyyMMdd")) ;	//交易日期		   
//				    td.setOutEntityno(String outEntityno);//外部实体编号
			    td. setBusinessNo(b.getBusinessNo());//
			    td. setPaymentType(AccountContants.PAYMENT_TYPE_CASH);//支付方式  0 现金 1 兑换券  默认为0
			    td.setPaymentTypeExt(AccountContants.STATUS_INVALID);//支付方式是否扩展 0 否1 是  默认为0
			    td.setRealTxnAmt(fr.getFeeBln());
			    tdm.insert(td);

				// 交易明细流水表
				TransGlide tg = new TransGlide();
				tg.setAcceptTp(AccountContants.ACCEPTANCE_TYPE_NET);// 受理类型
				//tg.setAccountType(AccountContants.WALLET_TYPE_ELECTRONIC_WALLET);// 账户类型
				// tg.setAllowReturn(AccountContants.STATUS_INVALID);//不可退费
				tg.setAppFlag(ak.getAppFlag());// 应用标识
				tg.setAppType(String.valueOf(ak.getAppType()));// 应用类型
				tg.setBranchNo(activeUser.getBranchNo());
				 tg.setBusinessNo(b.getBusinessNo());//业务流水号
				tg.setCitizenCardNo(citizenCardNo);// 市民卡号
				tg.setCashFlag(AccountContants.CASH_FLAG_PAY);// 现金收付标志
				 tg.setFeeRuleId(fr.getFeeRuleId());//卡费用规则ID
				 tg.setFeeRulesId(fr.getFeeRulesId());//卡费用细则ID
				tg.setFeeTp(AccountContants.FEE_TYPE_DEPOSIT);// 费用类型
				// tg.setIsReturned(AccountContants.STATUS_VALID);//是否已退费
				tg.setOprNo(activeUser.getUserNo().toString());
				tg.setPaymentType(AccountContants.PAYMENT_TYPE_CASH);// 现金

				tg.setPaymentTypeExt(AccountContants.STATUS_INVALID);
				// tg.setRptDate(rptDate);//轧帐日期
				tg.setRptFlag(AccountContants.RPT_FLAG_NO);// 轧帐标识 0未过账
				// tg.setSubaccountNo(subaccountNo);//网点子账号
				// tg.setReturnTransGlideId(returnTransGlideId);//退费交易明细流水ID
				tg.setTxnAdjFlg(AccountContants.TRANSACTION_FLOW_FLAG_NORMAL);// 交易流水标识
				
				if(ak.getAppFlag().equals(AppContants.APP_FLAG_BIKE)){
					tg.setTxnAmt(fr.getFeeBln().add(new BigDecimal(balance)));// 交易金额
				}else{
					tg.setTxnAmt(fr.getFeeBln());// 交易金额
				}
				tg.setTxnDt(now);// 交易时间
				tg.setTxnTp(AccountContants.TXNTP_REFUND);// txnTp 交易类型

				tgm.insert(tg);
			}
				
		}
		
		
		for(AppKind appKind:appKinds){
			if(appKind.getAppFlag().equals(AppContants.APP_FLAG_BIKE)){
				String vipno=(String) SecurityUtils.getSubject().getSession().getAttribute("vipno");
				SecurityUtils.getSubject().getSession().removeAttribute("vipno");
				JSONObject jsonObject=bikeService.backCard(vipno);
				ResponseHead g =JSON.parseObject(jsonObject.getString("head"), ResponseHead.class);
				if(!code0000.equals(g.getRsltcode())){
		        	throw new ApplicationException(ErrorCode.OTHER_EXCEPTION, "自行车应用退卡失败");
		        }
			}
		}
		String str = "{\"title\":\""+"联名卡注销凭证"+"\",\"type\":\""+"cancelRefund"+"\",\"certNo\":\""+ce.getCertNo()+"\",\"busType\":\""
		+CardContants.getCertTypeNameByCode(ce.getCertType())+"\",\"cardType\":\""+ce.getCardTypecode()+"\",\"citizenCardNo\":\""
		+cd.getCitizenCardNo()+"\",\"fee\":\""+(new DecimalFormat("0.00")).format(refundFeeBln)+"\",\"money\":\""
		+(new DecimalFormat("0.00")).format(logofMoney)+"\",\"net\":\""+activeUser.getBranchName()+"\",\"operator\":\""
		+activeUser.getUserNo().toString()+"\",\"date\":\""+DateFormatUtils.format(new Date(), "yyyy-MM-dd")+"\"}";
		ce.setData(str);
		ce.setTransCode("联名卡注销登记");
		cem.update(ce);
		
		VoucherVo vv = new VoucherVo();
		vv.setCertNo(ce.getCertNo());
		vv.setBusinessTypeName(CardContants.getCertTypeNameByCode(ce.getCertType()));
		vv.setCardType(cd.getCardTypecode());
		vv.setNewCitizenCardNo(cd.getCitizenCardNo());
		vv.setDate(DateFormatUtils.format(new Date(),"yyyy-MM-dd"));
		vv.setOperator(activeUser.getUserNo().toString());
		vv.setNet(activeUser.getBranchName());
		vv.setFeeBln(String.valueOf((new DecimalFormat("0.00")).format(refundFeeBln)));
		vv.setTransactionAmount(String.valueOf((new DecimalFormat("0.00")).format(logofMoney)));
		return vv;
	}

}
